fix: handle localStorage null (approach B: sentinel value)#83
Closed
fix: handle localStorage null (approach B: sentinel value)#83
Conversation
Use undefined as initial sentinel for storageItem ref instead of null, so the first render parsing branch always runs. Replace goodTry with try-catch in default-value writing to fall back to inMemoryData when localStorage is unavailable. Fixes #80
2 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #80 — Firefox with
dom.storage.enabled: falsesetslocalStoragetonull, causing the hook to break.Approach: Fix initial ref sentinel value
The root cause:
storageItem.current.stringis initialized tonull, and whenlocalStorage.getItem()fails,goodTryreturnsundefinedwhich gets coerced tonull. Since both values arenull, the comparisonstring !== storageItem.current.stringisfalse, skipping the parsing branch — the value staysundefinedinstead ofdefaultValue.Changes:
storageItemref initialstringfromnulltoundefined, so first-render comparisonnull !== undefinedistrue— the parsing branch always runsgoodTrywithtry-catchthat falls back toinMemoryData.set(key, defaultValue)when localStorage is unavailablestorageItem.current.stringtoundefinedso getSnapshot re-parses correctly after removal when localStorage is unavailableWhy this approach:
undefinedsentinel is semantically correct: "not yet read from localStorage"inMemoryDatais populated, making the existingisPersistentlogic work correctlyAlternative approach
See PR #82 for approach A (detect unavailability) — a different way to solve the same issue.
Next.js test projects
To test in Firefox with
dom.storage.enabled: falseinabout:config:Test plan
localStoragebeingnullviavi.spyOn(window, 'localStorage', 'get').mockReturnValue(null)